package com.uinnova.product.eam.web.eam.peer.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.lang.NumberUtils;
import com.binary.core.lang.StringUtils;
import com.binary.core.util.BinaryUtils;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.VcDiagramDir;
import com.uinnova.product.eam.comm.model.es.*;
import com.uinnova.product.eam.model.AssetWarehouseDirVo;
import com.uinnova.product.eam.model.cj.domain.DirRelationPlan;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.enums.CategoryTypeEnum;
import com.uinnova.product.eam.model.enums.ModelTypeEnum;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.bm.EsDiagramCatalogDesignDao;
import com.uinnova.product.eam.service.bm.EsDiagramCatalogPrivateDao;
import com.uinnova.product.eam.service.cj.dao.DirRelationPlanDao;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.es.*;
import com.uinnova.product.eam.web.eam.peer.IFlushPeer;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.db.eam.ESDiagramDao;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysUser;
import com.uino.dao.util.ESUtil;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 刷数据接口实现
 */
@Service
@Slf4j
public class FlushPeerImpl implements IFlushPeer {
    @Resource
    private EsDiagramCatalogPrivateDao oldDirPrivateDao;
    @Resource
    private EsDiagramCatalogDesignDao oldDirDesignDao;
    @Resource
    private EamCategoryPrivateDao categoryPrivateDao;
    @Resource
    private EamCategoryDesignDao categoryDesignDao;
    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    private IBmMultiModelHierarchySvc modelHierarchySvc;
    @Resource
    private BmConfigSvc bmConfigSvc;
    @Resource
    private PlanDesignInstanceService planDesignInstanceService;
    @Resource
    private DirRelationPlanDao dirRelationPlanDao;
    @Resource
    private IUserApiSvc userApiSvc;
    @Resource
    private IFolderPermissionManagerService folderPermissionManagerService;
    @Resource
    private EamVersionTagDao versionTagDao;
    @Resource
    private EamVersionDirDao versionDirDao;

    private static final String FLOW_MODEL_DIR_CONFIG = "{\"businessModel\": \"业务架构资产库\",\"dataModel\": \"业务架构资产库\"," +
            "\"productPlanModel\": \"产品设计库\",\"appModel\": \"企业级IT架构资产库\",\"technicalModel\": \"企业级IT架构资产库\"}";

    @Resource
    private VcDiagramSvc vcDiagramSvc;
    @Resource
    private IamsEsDiagramDirDao iamsEsDiagramDirDao;
    @Resource
    private ESDiagramDao diagramDao;
    @Resource
    private IEamArtifactSvc artifactSvc;

    @Resource
    AssetWarehouseDirDao assetWarehouseDirDao;
    @Resource
    AssetWarehouseDirSvc assetWarehouseDirSvc;


    @Override
    public void flushNewDir() {
        String configJson = bmConfigSvc.getConfigType("FLOW_MODEL_DIR_CONFIG");
        if(BinaryUtils.isEmpty(configJson)){
            configJson = FLOW_MODEL_DIR_CONFIG;
        }
        log.info("================资产仓库配置:{}",configJson);
        JSONObject config = JSON.parseObject(configJson);
        long businessModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("businessModel")).hashCode() & Integer.MAX_VALUE));
        long dataModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("dataModel")).hashCode() & Integer.MAX_VALUE));
        long productPlanModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("productPlanModel")).hashCode() & Integer.MAX_VALUE));
        long appModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("appModel")).hashCode() & Integer.MAX_VALUE));
        long technicalModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("technicalModel")).hashCode() & Integer.MAX_VALUE));
        // 生成顶级目录，同时生成资产仓库菜单树
        flushAssetWarehouseDir(config, businessModelId,dataModelId,productPlanModelId,appModelId,technicalModelId);
        flushModelType();
        flushBusinessDir(businessModelId, dataModelId);
        flushDiagram(businessModelId, productPlanModelId, appModelId);
    }

    private void flushAssetWarehouseDir(JSONObject config, long businessModelId, long dataModelId, long productPlanModelId, long appModelId, long technicalModelId) {
        List<AssetWarehouseDirVo> dirList = new ArrayList<>();
        createAssetWarehousDir(config, businessModelId, dirList,"businessModel");
        createAssetWarehousDir(config, dataModelId, dirList,"dataModel");
        createAssetWarehousDir(config, productPlanModelId, dirList,"productPlanModel");
        createAssetWarehousDir(config, appModelId,dirList,"appModel");
//        createAssetWarehousDir(config, technicalModelId, assetModule, dirList,"technicalModel");
        // 过滤存在仓库不进行修改
        List<AssetWarehouseDir> listByQuery = assetWarehouseDirDao.getListByQuery(QueryBuilders.termQuery("parentId", 0));
        List<Long> idList = Collections.emptyList();
        if (!CollectionUtils.isEmpty(listByQuery)) {
            idList = listByQuery.stream().map(AssetWarehouseDir::getId).collect(Collectors.toList());
        }
        List<AssetWarehouseDirVo> saveList = new ArrayList<>();
        Iterator<AssetWarehouseDirVo> iterator = dirList.iterator();
        while (iterator.hasNext()) {
            AssetWarehouseDirVo next = iterator.next();
            Long id = next.getId();
            if (idList.contains(id)) {
                iterator.remove();
            }
            // 过滤重复数据
            if (!saveList.contains(next)) {
                saveList.add(next);
            }
        }
        if (!CollectionUtils.isEmpty(saveList)) {
            assetWarehouseDirSvc.saveOrUpdate(saveList);
        }
    }

    private void createAssetWarehousDir(JSONObject config, long businessModelId, List<AssetWarehouseDirVo> dirList,String key) {
        AssetWarehouseDirVo businessModelDir = new AssetWarehouseDirVo();
        businessModelDir.setId(businessModelId);
        businessModelDir.setName(config.getString(key));
        businessModelDir.setRoleIdList(Lists.newArrayList(1L));
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();
        businessModelDir.setModuleUrl("/framework-assets#/assets/");
        businessModelDir.setCreator(currentUserInfo.getLoginCode());
        businessModelDir.setModifier(currentUserInfo.getLoginCode());
        businessModelDir.setCreateTime(System.currentTimeMillis());
        businessModelDir.setModifyTime(System.currentTimeMillis());
        businessModelDir.setModuleType(3);
        businessModelDir.setParentId(0L);
        businessModelDir.setAssetType(Lists.newArrayList(1,2,3));
        businessModelDir.setDomainId(currentUserInfo.getDomainId());
        dirList.add(businessModelDir);
    }

    public void flushDiagram(long businessModelId, long productPlanModelId,long appModelId) {
        List<EamArtifact> artifacts = artifactSvc.queryByConditions(new EamArtifact());
        Map<Long, EamArtifact> artifactMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(artifacts)){
            artifactMap = artifacts.stream().collect(Collectors.toMap(EamArtifact::getId, e -> e, (k1, k2) -> k2));
        }
        List<ESDiagram> diagramList = diagramDao.getListByQueryScroll(QueryBuilders.boolQuery());
        if(CollectionUtils.isEmpty(diagramList)){
            return;
        }
        for (ESDiagram each : diagramList) {
            if(BinaryUtils.isEmpty(each.getViewType())){
                each.setDirType(0);
            }else{
                if(NumberUtils.isLong(each.getViewType())){
                    EamArtifact artifact = artifactMap.get(Long.parseLong(each.getViewType()));
                    each.setDirType(artifact==null?0:artifact.getTypeClassification());
                }else{
                    each.setDirType(0);
                    each.setViewType("0");
                }
            }
            if(each.getIsOpen()==0 && (each.getDirId().equals(1L))){
                each.setDirId(0L);
            }else if(each.getIsOpen()==1){
                if(each.getDirId().equals(0L)){
                    each.setDirId(businessModelId);
                }else if(each.getDirId().equals(1L)){
                    each.setDirId(appModelId);
                }else if(each.getDirId().equals(5L)){
                    each.setDirId(productPlanModelId);
                }
            }
        }
        diagramDao.saveOrUpdateBatch(diagramList);
    }

    @Override
    public void flushModelType() {
        //刷新模型树类型  数据接口
        List<EamMultiModelHierarchy> modelHierarchies = modelHierarchySvc.queryList(null, 1);
        if(!BinaryUtils.isEmpty(modelHierarchies)) {
            return;
        }
        for (EamMultiModelHierarchy modelHierarchy : modelHierarchies) {
            if(!BinaryUtils.isEmpty(modelHierarchy.getModelType())){
                continue;
            }
            EamMultiModelType type = modelHierarchy.getType();
            if(type!=null && "数据建模".equals(type.getName())){
                modelHierarchy.setModelType(ModelTypeEnum.DATA.val());
            }else{
                modelHierarchy.setModelType(ModelTypeEnum.BUSINESS.val());
            }
        }
        modelHierarchySvc.saveOrUpdateBatch(modelHierarchies);
    }

    @Override
    public void flushBusinessDir(long businessModelId, long dataModelId) {
        List<EamMultiModelHierarchy> hierarchyList = modelHierarchySvc.queryList(null, null);
        Map<Long, EamMultiModelHierarchy> hierarchyMap = hierarchyList.stream().collect(Collectors.toMap(EamMultiModelHierarchy::getId, e -> e, (k1, k2) -> k2));
        flushCatalogDir(hierarchyMap, businessModelId, dataModelId, LibType.PRIVATE);
        flushCatalogDir(hierarchyMap, businessModelId, dataModelId, LibType.DESIGN);
    }

    private void flushCatalogDir(Map<Long, EamMultiModelHierarchy> hierarchyMap, long businessModelId, long dataModelId, LibType libType) {
        List<EamDiagramCatalog> dirList;
        if(LibType.PRIVATE.equals(libType)){
            dirList = oldDirPrivateDao.getListByQueryScroll(QueryBuilders.boolQuery());
        }else{
            dirList = oldDirDesignDao.getListByQueryScroll(QueryBuilders.boolQuery());
        }
        if(CollectionUtils.isEmpty(dirList)){
            return;
        }

        dirList.sort(Comparator.comparing(EamDiagramCatalog::getDirLvl));
        Map<Long, EamCategory> parentMap = new HashMap<>();
        for (EamDiagramCatalog old : dirList) {
            if(BinaryUtils.isEmpty(old.getModelId())){
                continue;
            }
            //目录的顶级，需要创建个模型文件夹
            EamCategory category = EamUtil.copy(old, EamCategory.class);
            category.setCiCode(old.getAssetCode());
            Long parentId = old.getParentDirCode();
            if(old.getDirLvl()==0){
                EamMultiModelHierarchy hierarchy = hierarchyMap.get(old.getModelId());
                EamCategory root = this.createModelDir(old, hierarchy, businessModelId, dataModelId, libType);
                parentMap.put(root.getId(), root);
                parentId = root.getId();
                category.setCiCode(root.getCiCode());
            }
            EamCategory parent = parentMap.get(parentId);
            if(parent == null){
                continue;
            }
            if(BinaryUtils.isEmpty(category.getOwnerCode())){
                category.setOwnerCode(old.getCreator());
            }
            category.setParentId(parent.getId());
            category.setDirLvl(parent.getDirLvl() + 1);
            category.setDirPath(parent.getDirPath() + category.getId() + "#");
            category.setType(CategoryTypeEnum.MODEL.val());
            category.setDataStatus(1);
            parentMap.put(category.getId(), category);
        }
        categorySvc.saveOrUpdateList(new ArrayList<>(parentMap.values()), libType);
    }

    /**
     * 创建顶级模型文件夹
     */
    private EamCategory createModelDir(EamDiagramCatalog old, EamMultiModelHierarchy hierarchy, long businessModelId, long dataModelId, LibType libType){
        EamCategory model = categorySvc.getModelRoot(old.getModelId(), old.getOwnerCode(), libType);
        if(model == null){
            model = new EamCategory();
            model.setId(ESUtil.getUUID());
        }
        String dirName = hierarchy==null?"模型工艺已删除":hierarchy.getName();
        model.setDirName(dirName);
        model.setDomainId(old.getDomainId());
        model.setCiCode(old.getModelId().toString());
        if(LibType.PRIVATE.equals(libType)){
            model.setParentId(0L);
            model.setDirLvl(1);
            model.setDirPath("#"+model.getId()+"#");
        }else{
            if(hierarchy==null || hierarchy.getType()==null || hierarchy.getModelType()==null || hierarchy.getModelType() == ModelTypeEnum.BUSINESS.val()){
                model.setParentId(businessModelId);
            }else{
                model.setParentId(dataModelId);
            }
            model.setDirLvl(2);
            model.setDirPath("#"+model.getParentId()+"#"+model.getId()+"#");
        }
        model.setModelId(old.getModelId());
        model.setType(CategoryTypeEnum.MODEL_ROOT.val());
        model.setDataStatus(1);
        model.setOwnerCode(old.getOwnerCode());
        model.setCreator(old.getCreator());
        model.setModifier(old.getModifier());
        model.setCreateTime(old.getCreateTime());
        model.setModifyTime(old.getModifyTime());
        return model;
    }

    @Override
    public void flushPlanData() {

    }

    @Override
    public void flushGeneralDir() {
        // 1. 清洗私有库dir历史数据
        List<Long> unequalIds = Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 1087638491356966L, 1087638491356968L, 1087638491356992L, 1087638491356996L);

        SysUser sysUser = SysUtil.getCurrentUserInfo();
        List<VcDiagramDir> vcDiagramDirs = vcDiagramSvc.queryDiagramDirList(sysUser.getDomainId(), null, null);
        if (!CollectionUtils.isEmpty(vcDiagramDirs)) {
            List<EamCategory> records = new ArrayList<>();
            for (VcDiagramDir dir : vcDiagramDirs) {
                if (unequalIds.contains(dir.getId())) {
                    continue;
                }
                EamCategory eamCategory = new EamCategory();
                BeanUtils.copyProperties(dir, eamCategory);
                eamCategory.setCiCode(dir.getEsSysId());
                eamCategory.setType(CategoryTypeEnum.UNIVERSAL.val());
                eamCategory.setOwnerCode(dir.getCreator());
                if (Objects.equals(dir.getDirLvl(), 1)) {
                    eamCategory.setParentId(0L);
                }
                records.add(eamCategory);
            }
            if (!CollectionUtils.isEmpty(records)) {
                categorySvc.saveOrUpdateList(records, LibType.PRIVATE);
            }
        }

        // 2. 清洗设计库dir历史数据
        String configJson = bmConfigSvc.getConfigType("FLOW_MODEL_DIR_CONFIG");
        if(BinaryUtils.isEmpty(configJson)){
            configJson = FLOW_MODEL_DIR_CONFIG;
        }
        log.info("================资产仓库配置:{}",configJson);
        JSONObject config = JSON.parseObject(configJson);
        long businessModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("businessModel")).hashCode() & Integer.MAX_VALUE));
        long productPlanModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("productPlanModel")).hashCode() & Integer.MAX_VALUE));
        long appModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("appModel")).hashCode() & Integer.MAX_VALUE));
        long technicalModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("technicalModel")).hashCode() & Integer.MAX_VALUE));
        //清洗产品方案资产数据
        dealDirByType(productPlanModelId, 110, 5L);
        //清洗应用架构资产数据
        dealDirByType(appModelId, 11, 1L);
        //清洗技术架构资产数
        dealDirByType(technicalModelId, 111, 0L);
        //组建模型及其他模型资产
        dealDirByType(businessModelId, 100, 0L);
        dealDirByType(businessModelId, 1, 0L);
    }

    /**
     * 根据原资产类型分别放入对应资产仓库
     * @param assetRootId 资产目录根id
     * @param dirType 目录类型
     * @param parentId 父级id
     */
    private void dealDirByType(long assetRootId, int dirType, Long parentId){
        List<EamDiagramDir> diagramDirList = iamsEsDiagramDirDao.findDiagramDirList(null, dirType, null);
        if (CollectionUtils.isEmpty(diagramDirList)) {
            return;
        }
        diagramDirList.sort(Comparator.comparing(EamDiagramDir::getDirLvl));
        Map<Long, EamCategory> parentMap = new HashMap<>();
        Map<Long, List<EamDiagramDir>> dirGroup = diagramDirList.stream().collect(Collectors.groupingBy(EamDiagramDir::getParentId));

        getChild(parentId, dirGroup, parentMap, assetRootId);
        List<EamCategory> saveList = new ArrayList<>(parentMap.values());
        if(CollectionUtils.isEmpty(saveList)){
            return;
        }
        categorySvc.saveOrUpdateList(saveList, LibType.DESIGN);
    }

    private void getChild(Long parentId, Map<Long, List<EamDiagramDir>> dirGroup, Map<Long, EamCategory> parentMap, long productPlanModelId){
        List<EamDiagramDir> childList = dirGroup.get(parentId);
        if(CollectionUtils.isEmpty(childList)){
            return;
        }
        for (EamDiagramDir each : childList) {
            EamCategory category = EamUtil.copy(each, EamCategory.class);
            if(parentId.equals(5L) || parentId.equals(1L) || parentId.equals(0L)){
                category.setParentId(productPlanModelId);
                category.setDirLvl(2);
                category.setDirPath("#"+productPlanModelId+"#"+category.getId()+"#");
            }else{
                EamCategory parentCategory = parentMap.get(each.getParentId());
                if(parentCategory == null){
                    continue;
                }
                category.setDirLvl(parentCategory.getDirLvl()+1);
                category.setDirPath(parentCategory.getDirPath()+category.getId()+"#");
            }
            category.setOwnerCode(each.getCreator());
            category.setType(CategoryTypeEnum.UNIVERSAL.val());
            category.setCiCode(each.getEsSysId());
            parentMap.put(category.getId(), category);
            getChild(each.getId(), dirGroup, parentMap, productPlanModelId);
        }
    }

    @Override
    public void flushSystemDir() {
        List<EamCategory> privateList = categoryPrivateDao.getListByQueryScroll(QueryBuilders.boolQuery());
        for (EamCategory category : privateList) {
            if(category.getType()==CategoryTypeEnum.SYSTEM.val() || category.getType()==CategoryTypeEnum.CLASSIFY.val()){
                category.setType(CategoryTypeEnum.UNIVERSAL.val());
            }
        }
        categoryPrivateDao.saveOrUpdateBatch(privateList);
        List<EamCategory> designList = categoryDesignDao.getListByQueryScroll(QueryBuilders.boolQuery());
        for (EamCategory category : designList) {
            if(category.getType()==CategoryTypeEnum.SYSTEM.val() || category.getType()==CategoryTypeEnum.CLASSIFY.val()){
                category.setType(CategoryTypeEnum.UNIVERSAL.val());
            }
        }
        categoryDesignDao.saveOrUpdateBatch(designList);
    }

    @Override
    public void flushPlan() {
        // 1. 清洗方案的dirId数据
        List<PlanDesignInstance> privatePlanList = planDesignInstanceService.findPlanInstanceListByDirId(1L, null);
        if (!CollectionUtils.isEmpty(privatePlanList)) {
            for (PlanDesignInstance plan : privatePlanList) {
                plan.setDirId(0L);
            }
            planDesignInstanceService.updatePlanBatch(privatePlanList);
        }

        // 2. 清洗方案的assetsDirId数据
        String configJson = bmConfigSvc.getConfigType("FLOW_MODEL_DIR_CONFIG");
        if(BinaryUtils.isEmpty(configJson)){
            configJson = FLOW_MODEL_DIR_CONFIG;
        }
        JSONObject config = JSON.parseObject(configJson);
        long businessModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("businessModel")).hashCode() & Integer.MAX_VALUE));
        long productPlanModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("productPlanModel")).hashCode() & Integer.MAX_VALUE));
        long technicalModelId = Long.parseLong(String.valueOf(("QUICK_EA"+config.getString("technicalModel")).hashCode() & Integer.MAX_VALUE));

        List<Long> assetsDirIds = Arrays.asList(0L, 1L, 5L);
        List<PlanDesignInstance> designPlanList = planDesignInstanceService.findPlanInstanceListByDirId(null, assetsDirIds);
        if (!CollectionUtils.isEmpty(designPlanList)) {
            for (PlanDesignInstance plan : designPlanList) {
                if (Objects.equals(plan.getAssetsDirId(), 0L)) {
                    plan.setAssetsDirId(businessModelId);
                } else if (Objects.equals(plan.getAssetsDirId(), 1L)) {
                    plan.setAssetsDirId(technicalModelId);
                } else if (Objects.equals(plan.getAssetsDirId(), 5L)) {
                    plan.setAssetsDirId(productPlanModelId);
                }
            }
            planDesignInstanceService.updatePlanBatch(designPlanList);
        }

        // 3.清洗资产方案assetsDirId
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        List<DirRelationPlan> dirRelationPlanList = dirRelationPlanDao.getListByQuery(queryBuilder);
        if (!CollectionUtils.isEmpty(dirRelationPlanList)) {
            List<PlanDesignInstance> assetsPlanList = new ArrayList<>();
            for (DirRelationPlan dirRelationPlan : dirRelationPlanList) {
                PlanDesignInstance planDesignInstance = planDesignInstanceService.getPlanDesignInstance(dirRelationPlan.getPlanId());
                if (planDesignInstance == null) {
                    continue;
                }
                planDesignInstance.setAssetsDirId(dirRelationPlan.getDirId());
                assetsPlanList.add(planDesignInstance);
            }
            planDesignInstanceService.updatePlanBatch(assetsPlanList);
        }

    }

    public void refreshCategoryDirLvl(){
        List<EamCategory> categoryList = categoryPrivateDao.getListByQueryScroll(QueryBuilders.boolQuery());
        Map<Long, List<EamCategory>> dirGroup = categoryList.stream().collect(Collectors.groupingBy(EamCategory::getParentId));
        Map<Long, EamCategory> parentMap = new HashMap<>();
        setDirLvl(0L, dirGroup, parentMap);
        categoryPrivateDao.saveOrUpdateBatch(new ArrayList<>(parentMap.values()));
    }

    private void setDirLvl(Long parentId, Map<Long, List<EamCategory>> dirGroup, Map<Long, EamCategory> parentMap){
        List<EamCategory> childList = dirGroup.get(parentId);
        if(CollectionUtils.isEmpty(childList)){
            return;
        }
        for (EamCategory category : childList) {
            if(parentId.equals(0L)){
                category.setDirLvl(1);
            }else{
                EamCategory parentCategory = parentMap.get(parentId);
                if(parentCategory == null){
                    continue;
                }
                category.setDirLvl(parentCategory.getDirLvl()+1);
            }
            parentMap.put(category.getId(), category);
            setDirLvl(category.getId(), dirGroup, parentMap);
        }
    }

    /**
     * 修复新版目录创建目录时未依据父目录权限同步创建权限
     */
    public Integer designCategoryPermissionFix() {
        //1.获取资产库目录
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("dataStatus", 1));
        List<EamCategory> designCategories = categoryDesignDao.getListByQuery(query);
        if (CollectionUtils.isEmpty(designCategories)) {
            log.info("资产库目录列表为空");
            return 0;
        }
        Map<Long, EamCategory> categoryMap = designCategories.stream().collect(Collectors.toMap(EamCategory::getId, e -> e));
        //2.资产库目录权限
        List<Long> dirIds = designCategories.stream().map(EamCategory::getId).collect(Collectors.toList());
        List<FolderPermissionManager> permissions = folderPermissionManagerService.getFolderPermissionByDirIds(dirIds);
        Map<Long, List<FolderPermissionManager>> permissionGroupByDirId =
                permissions.stream().collect(Collectors.groupingBy(FolderPermissionManager::getDirId));
        //3.处理资产库目录权限
        List<FolderPermissionManager> fixPermissions = new ArrayList<>();
        Set<Integer> ignoreCategoryType = Stream.of(CategoryTypeEnum.ROOT.val(), CategoryTypeEnum.MODEL.val()).collect(Collectors.toSet());
        for (EamCategory category : designCategories) {
            if (category.getParentId() == 0 || ignoreCategoryType.contains(category.getType())) {
                continue;
            }
            //看下当前目录有没有配置权限
            List<FolderPermissionManager> currentPermissions = permissionGroupByDirId.get(category.getId());
            if (!CollectionUtils.isEmpty(currentPermissions)) {
                continue;
            }
            //看下上级目录有没有配置权限
            List<FolderPermissionManager> parentPermissions = this.getParentPermissions(category, permissionGroupByDirId);
            if (CollectionUtils.isEmpty(parentPermissions)) {
                continue;
            }
            //继承上级目录权限
            for (FolderPermissionManager folderPermission : parentPermissions) {
                folderPermission.setExtendPermission(Boolean.TRUE);
                folderPermission.setDirId(category.getId());
                folderPermission.setId(ESUtil.getUUID());
                fixPermissions.add(folderPermission);
            }
        }
        folderPermissionManagerService.saveFolderPermissions(fixPermissions);
        return fixPermissions.size();
    }


    private List<FolderPermissionManager> getParentPermissions(EamCategory category
            ,Map<Long, List<FolderPermissionManager>> permissionGroupByDirId) {
        List<FolderPermissionManager> permissions = new ArrayList<>();
        if (StringUtils.isBlank(category.getDirPath())) {
            return permissions;
        }
        //掐头去尾
        String dirPath = category.getDirPath().substring(1, category.getDirPath().length() - 1);
        String[] dirIds = dirPath.split("#");
        for (int i = dirIds.length - 1; i >= 0; i--) {
            //排除当前
            Long dirId = Long.valueOf(dirIds[i]);
            if (category.getId().equals(dirId)) {
                continue;
            }
            if (permissionGroupByDirId.containsKey(dirId)) {

                List<FolderPermissionManager> folderPermissionManagers = permissionGroupByDirId.get(dirId);
                //取出权限范围作用到子文件夹的权限
                for (FolderPermissionManager folderPermission : folderPermissionManagers) {
                    if (folderPermission.getFolderApplicationScope().getChildFolderAndFile()) {
                        permissions.add(folderPermission);
                    }
                }
                return permissions;
            }
        }
        return permissions;
    }

    @Override
    public Map<String, Integer> flushModelPermission() {
        List<FolderPermissionManager> folderPermissionManagers = folderPermissionManagerService.queryEmptyModelPermission();
        Map<String, Integer> result = new HashMap<>();
        if (CollectionUtils.isEmpty(folderPermissionManagers)) {
            result.put("fixCount", 0);
            result.put("noUseCount", 0);
            return result;
        }
        //获取资产库目录
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termsQuery("id", folderPermissionManagers
                .stream().map(FolderPermissionManager::getDirId).collect(Collectors.toSet())));
        query.must(QueryBuilders.termQuery("dataStatus", 1));
        List<EamCategory> designCategories = categoryDesignDao.getListByQuery(query);

        Set<Long> existDirIds = designCategories.stream().map(EamCategory::getId).collect(Collectors.toSet());
        int count = 0;
        Set<Long> hasDeletedDirPermissionIds = new HashSet<>();
        for (FolderPermissionManager folderPermissionManager : folderPermissionManagers) {
            if (!existDirIds.contains(folderPermissionManager.getDirId())) {
                hasDeletedDirPermissionIds.add(folderPermissionManager.getId());
                continue;
            }
            count++;
            ModelPermission modelPermission = new ModelPermission();
            modelPermission.setRead(Boolean.TRUE);
            folderPermissionManager.setModelPermission(modelPermission);
            folderPermissionManagerService.updateFolderPermissionManager(folderPermissionManager);
        }
        //处理目录被删除有问题的模型权限
        if (!CollectionUtils.isEmpty(hasDeletedDirPermissionIds)) {
            folderPermissionManagerService.deleteFolderPermissionsByIds(hasDeletedDirPermissionIds);
        }
        result.put("fixCount", count);
        result.put("noUseCount", hasDeletedDirPermissionIds.size());
        return result;
    }

    @Override
    public Map<String, Integer> flushModelVersionTagDir() {
        Map<String, Integer> result = new HashMap<>();
        result.put("addCount", 0);
        result.put("updateCount", 0);
        //获取资产库目录用到的模型ids
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("type", CategoryTypeEnum.MODEL_ROOT.val()));
        query.must(QueryBuilders.termQuery("dataStatus", 1));
        List<EamCategory> designModelRoots = categoryDesignDao.getListByQuery(query);
        if (CollectionUtils.isEmpty(designModelRoots)) {
            return result;
        }
        Set<Long> modelIds = designModelRoots.stream()
                .filter(modelRoot -> modelRoot.getModelId() != null)
                .map(EamCategory::getModelId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(modelIds)) {
            return result;
        }
        designModelRoots.sort(Comparator.comparing(EamCategory::getCreateTime).reversed());
        Map<Long, EamCategory> modelRootCategoryMap = designModelRoots
                .stream().collect(Collectors.toMap(EamCategory::getModelId, e -> e, (m1,m2) -> m1));
        //模型对应的版本标签列表
        BoolQueryBuilder tagQuery = QueryBuilders.boolQuery();
        tagQuery.must(QueryBuilders.termsQuery("branchId", modelIds));
        tagQuery.must(QueryBuilders.termQuery("dataStatus", 1));
        List<EamVersionTag> tagList = versionTagDao.getListByQuery(tagQuery);
        if (CollectionUtils.isEmpty(tagList)) {
            return result;
        }
        Set<Long> tagIds = tagList.stream().map(EamVersionTag::getId).collect(Collectors.toSet());
        Map<Long, Long> tagBranchIdMap = tagList.stream().collect(Collectors.toMap(EamVersionTag::getId, EamVersionTag::getBranchId));
        //版本目录
        BoolQueryBuilder versionDirQuery = QueryBuilders.boolQuery();
        versionDirQuery.must(QueryBuilders.termsQuery("tagId", tagIds));
        List<EamVersionDir> versionDirs = versionDirDao.getListByQueryScroll(versionDirQuery);
        if (CollectionUtils.isEmpty(versionDirs)) {
            return result;
        }
        Map<Long, List<EamVersionDir>> verionDirGroupByTagIdMap =
                versionDirs.stream().collect(Collectors.groupingBy(EamVersionDir::getTagId));
        List<EamVersionDir> newVersionDirList = new ArrayList<>();
        List<EamVersionDir> updateParentId0List = new ArrayList<>();
        for (Long tagId : verionDirGroupByTagIdMap.keySet()) {
            List<EamVersionDir> tagDirs = verionDirGroupByTagIdMap.get(tagId);
            if (CollectionUtils.isEmpty(tagDirs)) {
                continue;
            }
            Long modelId = tagBranchIdMap.get(tagId);
            if (modelId == null) {
                continue;
            }
            EamCategory modelRoot = modelRootCategoryMap.get(modelId);
            if (modelRoot == null) {
                continue;
            }
            Set<Long> tagDirIds = tagDirs.stream().map(EamVersionDir::getDirId).collect(Collectors.toSet());
            if (tagDirIds.contains(modelRoot.getId())) {
                continue;
            }
            //取出parentId为0的版本目录
            List<EamVersionDir> parentId0 = tagDirs.stream()
                    .filter(versionDir -> versionDir.getParentDirId() == 0L)
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(parentId0)) {
                for (EamVersionDir dir : parentId0) {
                    dir.setParentDirId(modelRoot.getId());
                    updateParentId0List.add(dir);
                }
            }
            newVersionDirList.add(initNewModelRootDir(modelRoot, tagId));
        }
        if (!CollectionUtils.isEmpty(newVersionDirList)) {
            versionDirDao.saveOrUpdateBatch(newVersionDirList);
        }
        if (!CollectionUtils.isEmpty(updateParentId0List)) {
            versionDirDao.saveOrUpdateBatch(updateParentId0List);
        }
        result.put("addCount", newVersionDirList.size());
        result.put("updateCount", updateParentId0List.size());
        return result;
    }

    private EamVersionDir initNewModelRootDir(EamCategory modelRoot, Long tagId) {
        EamVersionDir newModelRootDir = new EamVersionDir();
        newModelRootDir.setId(ESUtil.getUUID());
        newModelRootDir.setCiCode(modelRoot.getCiCode());
        newModelRootDir.setParentDirId(modelRoot.getParentId());
        newModelRootDir.setTagId(tagId);
        newModelRootDir.setDirLvl(modelRoot.getDirLvl());
        newModelRootDir.setDirId(modelRoot.getId());
        newModelRootDir.setDirName(modelRoot.getDirName());
        return newModelRootDir;
    }
}
